package cn.tiger;

import java.util.concurrent.CountDownLatch;

/**
 *   该类是一个线程不安全的类，不使用原子类 想看线程安全版可以看 ThreadSafeNumIncrement
 * @see  ThreadSafeNumIncrement
 */
public class ThreadNotSafeNumIncrement {
    private volatile int num = 0;  // 保证可见性,不保证原子性

    private int getNum() {
        return num;
    }

    private void addNum() {
        num++;
    }

    /**
     *<br>可以发现，结果小于100000 ，说明线程不安全；
     * 线程不安全的原因在于num++不是原子操作，num++包含三个操作：读取num的值，num+1，将num的值写入内存，虽然读取和写入操作是原子操作，但是num+1不是原子操作，所以num++不是原子操作，所以线程不安全。
     * 虽然num使用了volatile修饰，是可见性，但是不保证原子性。</br>
     */
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 100000;

        ThreadNotSafeNumIncrement threadNotSafeNumIncrement = new ThreadNotSafeNumIncrement();
        CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            new Thread(threadNotSafeNumIncrement::addNum).start();
            countDownLatch.countDown();
        }
        countDownLatch.await(); // 主线程等待子线程结束
        System.out.println("多线程执行：" + threadNotSafeNumIncrement.getNum()); // 结果经常小于100000，偶尔可以到达100000  执行结果 99994、97730、100000



        // 单线程执行
        ThreadNotSafeNumIncrement threadNotSafeNumIncrement1 = new ThreadNotSafeNumIncrement();
        for (int i = 0; i < threadCount; i++) {
            threadNotSafeNumIncrement1.addNum();
        }
        System.out.println("单线程执行：" + threadNotSafeNumIncrement1.getNum()); // 单线程由于没有线程安全问题，结果为100000
    }
}
